﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Tokenizer.CSharpTokenizer
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using System.Collections.Generic;
using System.Web.Razor.Parser;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Resources;
using System.Web.Razor.Text;
using System.Web.Razor.Tokenizer.Symbols;

namespace System.Web.Razor.Tokenizer
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Represents a CSharp tokenizer.</summary>
  public class CSharpTokenizer : System.Web.Razor.Tokenizer.Tokenizer<CSharpSymbol, CSharpSymbolType>
  {
    private Dictionary<char, Func<CSharpSymbolType>> _operatorHandlers;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Initializes a new instance of the <see cref="T:System.Web.Razor.Tokenizer.CSharpTokenizer" /> class.</summary>
    /// <param name="source">The source.</param>
    public CSharpTokenizer(ITextDocument source)
      : base(source)
    {
      this.CurrentState = new StateMachine<CSharpSymbol>.State(this.Data);
      this._operatorHandlers = new Dictionary<char, Func<CSharpSymbolType>>()
      {
        {
          '-',
          new Func<CSharpSymbolType>(this.MinusOperator)
        },
        {
          '<',
          new Func<CSharpSymbolType>(this.LessThanOperator)
        },
        {
          '>',
          new Func<CSharpSymbolType>(this.GreaterThanOperator)
        },
        {
          '&',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.And, '=', CSharpSymbolType.AndAssign, '&', CSharpSymbolType.DoubleAnd)
        },
        {
          '|',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Or, '=', CSharpSymbolType.OrAssign, '|', CSharpSymbolType.DoubleOr)
        },
        {
          '+',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Plus, '=', CSharpSymbolType.PlusAssign, '+', CSharpSymbolType.Increment)
        },
        {
          '=',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Assign, '=', CSharpSymbolType.Equals, '>', CSharpSymbolType.GreaterThanEqual)
        },
        {
          '!',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Not, '=', CSharpSymbolType.NotEqual)
        },
        {
          '%',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Modulo, '=', CSharpSymbolType.ModuloAssign)
        },
        {
          '*',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Star, '=', CSharpSymbolType.MultiplyAssign)
        },
        {
          ':',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Colon, ':', CSharpSymbolType.DoubleColon)
        },
        {
          '?',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.QuestionMark, '?', CSharpSymbolType.NullCoalesce)
        },
        {
          '^',
          this.CreateTwoCharOperatorHandler(CSharpSymbolType.Xor, '=', CSharpSymbolType.XorAssign)
        },
        {
          '(',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.LeftParenthesis)
        },
        {
          ')',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.RightParenthesis)
        },
        {
          '{',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.LeftBrace)
        },
        {
          '}',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.RightBrace)
        },
        {
          '[',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.LeftBracket)
        },
        {
          ']',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.RightBracket)
        },
        {
          ',',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.Comma)
        },
        {
          ';',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.Semicolon)
        },
        {
          '~',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.Tilde)
        },
        {
          '#',
          (Func<CSharpSymbolType>) (() => CSharpSymbolType.Hash)
        }
      };
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the state of the machine.</summary>
    /// <returns>The state of the machine.</returns>
    protected override StateMachine<CSharpSymbol>.State StartState => new StateMachine<CSharpSymbol>.State(this.Data);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the razor comment type for the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</summary>
    /// <returns>The razor comment type for the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</returns>
    public override CSharpSymbolType RazorCommentType => CSharpSymbolType.RazorComment;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the razor comment transition type for the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</summary>
    /// <returns>The razor comment transition type for the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</returns>
    public override CSharpSymbolType RazorCommentTransitionType => CSharpSymbolType.RazorCommentTransition;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the star type of the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</summary>
    /// <returns>The star type of the <see cref="T:System.Web.Razor.Tokenizer.Symbols.CSharpSymbolType" />.</returns>
    public override CSharpSymbolType RazorCommentStarType => CSharpSymbolType.RazorCommentStar;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Creates a CSharp tokenizer symbol.</summary>
    /// <returns>A CSharp tokenizer symbol.</returns>
    /// <param name="start">The beginning of the source location.</param>
    /// <param name="content">The contents.</param>
    /// <param name="type">The CSharp symbol type.</param>
    /// <param name="errors">A collection of razor errors.</param>
    protected override CSharpSymbol CreateSymbol(
      SourceLocation start,
      string content,
      CSharpSymbolType type,
      IEnumerable<RazorError> errors)
    {
      return new CSharpSymbol(start, content, type, errors);
    }

    private StateMachine<CSharpSymbol>.StateResult Data()
    {
      if (ParserHelpers.IsNewLine(this.CurrentCharacter))
      {
        int num = this.CurrentCharacter == '\r' ? 1 : 0;
        this.TakeCurrent();
        if (num != 0 && this.CurrentCharacter == '\n')
          this.TakeCurrent();
        return this.Stay(this.EndSymbol(CSharpSymbolType.NewLine));
      }
      if (ParserHelpers.IsWhitespace(this.CurrentCharacter))
      {
        this.TakeUntil((Func<char, bool>) (c => !ParserHelpers.IsWhitespace(c)));
        return this.Stay(this.EndSymbol(CSharpSymbolType.WhiteSpace));
      }
      if (CSharpHelpers.IsIdentifierStart(this.CurrentCharacter))
        return this.Identifier();
      if (char.IsDigit(this.CurrentCharacter))
        return this.NumericLiteral();
      switch (this.CurrentCharacter)
      {
        case '"':
          this.TakeCurrent();
          return this.Transition((StateMachine<CSharpSymbol>.State) (() => this.QuotedLiteral('"', CSharpSymbolType.StringLiteral)));
        case '\'':
          this.TakeCurrent();
          return this.Transition((StateMachine<CSharpSymbol>.State) (() => this.QuotedLiteral('\'', CSharpSymbolType.CharacterLiteral)));
        case '.':
          return char.IsDigit(this.Peek()) ? this.RealLiteral() : this.Stay(this.Single(CSharpSymbolType.Dot));
        case '/':
          this.TakeCurrent();
          if (this.CurrentCharacter == '/')
          {
            this.TakeCurrent();
            return this.SingleLineComment();
          }
          if (this.CurrentCharacter == '*')
          {
            this.TakeCurrent();
            return this.Transition(new StateMachine<CSharpSymbol>.State(this.BlockComment));
          }
          if (this.CurrentCharacter != '=')
            return this.Stay(this.EndSymbol(CSharpSymbolType.Slash));
          this.TakeCurrent();
          return this.Stay(this.EndSymbol(CSharpSymbolType.DivideAssign));
        case '@':
          return this.AtSymbol();
        default:
          return this.Stay(this.EndSymbol(this.Operator()));
      }
    }

    private StateMachine<CSharpSymbol>.StateResult AtSymbol()
    {
      this.TakeCurrent();
      if (this.CurrentCharacter == '"')
      {
        this.TakeCurrent();
        return this.Transition(new StateMachine<CSharpSymbol>.State(this.VerbatimStringLiteral));
      }
      if (this.CurrentCharacter == '*')
        return this.Transition(this.EndSymbol(CSharpSymbolType.RazorCommentTransition), new StateMachine<CSharpSymbol>.State(((System.Web.Razor.Tokenizer.Tokenizer<CSharpSymbol, CSharpSymbolType>) this).AfterRazorCommentTransition));
      return this.CurrentCharacter == '@' ? this.Transition(this.EndSymbol(CSharpSymbolType.Transition), (StateMachine<CSharpSymbol>.State) (() =>
      {
        this.TakeCurrent();
        return this.Transition(this.EndSymbol(CSharpSymbolType.Transition), new StateMachine<CSharpSymbol>.State(this.Data));
      })) : this.Stay(this.EndSymbol(CSharpSymbolType.Transition));
    }

    private CSharpSymbolType Operator()
    {
      char currentCharacter = this.CurrentCharacter;
      this.TakeCurrent();
      Func<CSharpSymbolType> func;
      return this._operatorHandlers.TryGetValue(currentCharacter, out func) ? func() : CSharpSymbolType.Unknown;
    }

    private CSharpSymbolType LessThanOperator()
    {
      if (this.CurrentCharacter != '=')
        return CSharpSymbolType.LessThan;
      this.TakeCurrent();
      return CSharpSymbolType.LessThanEqual;
    }

    private CSharpSymbolType GreaterThanOperator()
    {
      if (this.CurrentCharacter != '=')
        return CSharpSymbolType.GreaterThan;
      this.TakeCurrent();
      return CSharpSymbolType.GreaterThanEqual;
    }

    private CSharpSymbolType MinusOperator()
    {
      if (this.CurrentCharacter == '>')
      {
        this.TakeCurrent();
        return CSharpSymbolType.Arrow;
      }
      if (this.CurrentCharacter == '-')
      {
        this.TakeCurrent();
        return CSharpSymbolType.Decrement;
      }
      if (this.CurrentCharacter != '=')
        return CSharpSymbolType.Minus;
      this.TakeCurrent();
      return CSharpSymbolType.MinusAssign;
    }

    private Func<CSharpSymbolType> CreateTwoCharOperatorHandler(
      CSharpSymbolType typeIfOnlyFirst,
      char second,
      CSharpSymbolType typeIfBoth)
    {
      return (Func<CSharpSymbolType>) (() =>
      {
        if ((int) this.CurrentCharacter != (int) second)
          return typeIfOnlyFirst;
        this.TakeCurrent();
        return typeIfBoth;
      });
    }

    private Func<CSharpSymbolType> CreateTwoCharOperatorHandler(
      CSharpSymbolType typeIfOnlyFirst,
      char option1,
      CSharpSymbolType typeIfOption1,
      char option2,
      CSharpSymbolType typeIfOption2)
    {
      return (Func<CSharpSymbolType>) (() =>
      {
        if ((int) this.CurrentCharacter == (int) option1)
        {
          this.TakeCurrent();
          return typeIfOption1;
        }
        if ((int) this.CurrentCharacter != (int) option2)
          return typeIfOnlyFirst;
        this.TakeCurrent();
        return typeIfOption2;
      });
    }

    private StateMachine<CSharpSymbol>.StateResult VerbatimStringLiteral()
    {
      this.TakeUntil((Func<char, bool>) (c => c == '"'));
      if (this.CurrentCharacter == '"')
      {
        this.TakeCurrent();
        if (this.CurrentCharacter == '"')
        {
          this.TakeCurrent();
          return this.Stay();
        }
      }
      else if (this.EndOfFile)
        this.CurrentErrors.Add(new RazorError(RazorResources.ParseError_Unterminated_String_Literal, this.CurrentStart));
      return this.Transition(this.EndSymbol(CSharpSymbolType.StringLiteral), new StateMachine<CSharpSymbol>.State(this.Data));
    }

    private StateMachine<CSharpSymbol>.StateResult QuotedLiteral(
      char quote,
      CSharpSymbolType literalType)
    {
      this.TakeUntil((Func<char, bool>) (c => c == '\\' || (int) c == (int) quote || ParserHelpers.IsNewLine(c)));
      if (this.CurrentCharacter == '\\')
      {
        this.TakeCurrent();
        if ((int) this.CurrentCharacter == (int) quote || this.CurrentCharacter == '\\')
          this.TakeCurrent();
        return this.Stay();
      }
      if (this.EndOfFile || ParserHelpers.IsNewLine(this.CurrentCharacter))
        this.CurrentErrors.Add(new RazorError(RazorResources.ParseError_Unterminated_String_Literal, this.CurrentStart));
      else
        this.TakeCurrent();
      return this.Transition(this.EndSymbol(literalType), new StateMachine<CSharpSymbol>.State(this.Data));
    }

    private StateMachine<CSharpSymbol>.StateResult BlockComment()
    {
      this.TakeUntil((Func<char, bool>) (c => c == '*'));
      if (this.EndOfFile)
      {
        this.CurrentErrors.Add(new RazorError(RazorResources.ParseError_BlockComment_Not_Terminated, this.CurrentStart));
        return this.Transition(this.EndSymbol(CSharpSymbolType.Comment), new StateMachine<CSharpSymbol>.State(this.Data));
      }
      if (this.CurrentCharacter == '*')
      {
        this.TakeCurrent();
        if (this.CurrentCharacter == '/')
        {
          this.TakeCurrent();
          return this.Transition(this.EndSymbol(CSharpSymbolType.Comment), new StateMachine<CSharpSymbol>.State(this.Data));
        }
      }
      return this.Stay();
    }

    private StateMachine<CSharpSymbol>.StateResult SingleLineComment()
    {
      this.TakeUntil((Func<char, bool>) (c => ParserHelpers.IsNewLine(c)));
      return this.Stay(this.EndSymbol(CSharpSymbolType.Comment));
    }

    private StateMachine<CSharpSymbol>.StateResult NumericLiteral() => this.TakeAll("0x", true) ? this.HexLiteral() : this.DecimalLiteral();

    private StateMachine<CSharpSymbol>.StateResult HexLiteral()
    {
      this.TakeUntil((Func<char, bool>) (c => !ParserHelpers.IsHexDigit(c)));
      this.TakeIntegerSuffix();
      return this.Stay(this.EndSymbol(CSharpSymbolType.IntegerLiteral));
    }

    private StateMachine<CSharpSymbol>.StateResult DecimalLiteral()
    {
      this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      if (this.CurrentCharacter == '.' && char.IsDigit(this.Peek()))
        return this.RealLiteral();
      if (CSharpHelpers.IsRealLiteralSuffix(this.CurrentCharacter) || this.CurrentCharacter == 'E' || this.CurrentCharacter == 'e')
        return this.RealLiteralExponentPart();
      this.TakeIntegerSuffix();
      return this.Stay(this.EndSymbol(CSharpSymbolType.IntegerLiteral));
    }

    private StateMachine<CSharpSymbol>.StateResult RealLiteralExponentPart()
    {
      if (this.CurrentCharacter == 'E' || this.CurrentCharacter == 'e')
      {
        this.TakeCurrent();
        if (this.CurrentCharacter == '+' || this.CurrentCharacter == '-')
          this.TakeCurrent();
        this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      }
      if (CSharpHelpers.IsRealLiteralSuffix(this.CurrentCharacter))
        this.TakeCurrent();
      return this.Stay(this.EndSymbol(CSharpSymbolType.RealLiteral));
    }

    private StateMachine<CSharpSymbol>.StateResult RealLiteral()
    {
      this.TakeCurrent();
      this.TakeUntil((Func<char, bool>) (c => !char.IsDigit(c)));
      return this.RealLiteralExponentPart();
    }

    private void TakeIntegerSuffix()
    {
      if (char.ToLowerInvariant(this.CurrentCharacter) == 'u')
      {
        this.TakeCurrent();
        if (char.ToLowerInvariant(this.CurrentCharacter) != 'l')
          return;
        this.TakeCurrent();
      }
      else
      {
        if (char.ToLowerInvariant(this.CurrentCharacter) != 'l')
          return;
        this.TakeCurrent();
        if (char.ToLowerInvariant(this.CurrentCharacter) != 'u')
          return;
        this.TakeCurrent();
      }
    }

    private StateMachine<CSharpSymbol>.StateResult Identifier()
    {
      this.TakeCurrent();
      this.TakeUntil((Func<char, bool>) (c => !CSharpHelpers.IsIdentifierPart(c)));
      CSharpSymbol output = (CSharpSymbol) null;
      if (this.HaveContent)
      {
        CSharpKeyword? nullable = CSharpKeywordDetector.SymbolTypeForIdentifier(this.Buffer.ToString());
        CSharpSymbolType type = CSharpSymbolType.Identifier;
        if (nullable.HasValue)
          type = CSharpSymbolType.Keyword;
        output = new CSharpSymbol(this.CurrentStart, this.Buffer.ToString(), type)
        {
          Keyword = nullable
        };
      }
      this.StartSymbol();
      return this.Stay(output);
    }
  }
}
